import json

import docker
from flask import Flask, render_template, request, jsonify
import paho.mqtt.client as mqtt
import pika
import threading

from container import create_container

app = Flask(__name__)

# MQTT配置
MQTT_BROKER = "192.168.6.235"
MQTT_PORT = 1883
MQTT_TOPIC_to_RES = "test_topic_from_grd"
MQTT_TOPIC_to_SEND = "test_topic_from_sat"

# RabbitMQ配置
RABBITMQ_QUEUE = 'test_queue'
RABBITMQ_QUEUE2 = 'from_node2_to_node1'

# MQTT客户端
mqtt_client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)

# 全局变量用于保存收到的消息
mqtt_received_message = None
rabbitmq_received_message = None


# MQTT收到消息的回调函数
def on_message(client, userdata, msg):
    global mqtt_received_message
    mqtt_received_message = msg.payload.decode()
    print("MQTT Received:", mqtt_received_message)
    if 'create!' in mqtt_received_message:
        # 将单引号替换为双引号
        json_str = mqtt_received_message.split('!')[1].replace("'", '"')

        # 解析 JSON 对象
        json_obj = json.loads(json_str)

        # 提取各键值对参数
        name = json_obj['name']
        cpu_cost = json_obj['cpu_cost']
        memory_cost = json_obj['memory_cost']
        image = json_obj['image']
        ports = json_obj['ports']

        print("JSON 对象:", json_obj)
        print("Name:", name)
        print("CPU Cost:", cpu_cost)
        print("Memory Cost:", memory_cost)
        print("Image:", image)
        print("Ports:", ports)

        container_name = name
        ports_str = ports
        memory = memory_cost  # 获取内存值
        cpu_percentage = float(cpu_cost)  # 获取CPU使用率

        # 确保内存值不低于6MB
        if memory is not None and int(memory) < 6:
            print("提示：内存限制不能低于6MB")
            return

        ports_dict = {}
        if ports_str:
            # 将端口字符串解析为字典
            ports_list = ports_str.split(',')
            for port_pair in ports_list:
                host_port, container_port = port_pair.split(':')
                ports_dict[f'{container_port}/tcp'] = int(host_port)
        print(ports_dict)
        # 创建并启动新容器
        container_id = create_container(image, container_name, ports_dict, memory, cpu_percentage)
        if container_id is 2:
            send_rabbitmq_message_2("Please Creat xxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
        elif container_id is not None:
            mqtt_client.publish(MQTT_TOPIC_to_SEND, "create! successfully")
        else:
            mqtt_client.publish(MQTT_TOPIC_to_SEND, "create! error")

    if 'query!' in mqtt_received_message:
        client2 = docker.from_env()
        containers = client2.containers.list(all=True)  # 获取所有容器，包括Exited和Created状态的容器
        containers_data = []
        for container in containers:
            container_data = {
                'location':"node1",
                'id': container.id,
                'name': container.name,
                'status': container.status,
                'cpu_usage_percentage': None,
                'memory_usage': container.attrs['HostConfig']['Memory'] / (1024 * 1024),  # 将内存从B转换为MB
                'memory_limit': container.attrs['HostConfig']['Memory'] / (1024 * 1024),  # 将内存从B转换为MB
                'ports': container.attrs['NetworkSettings']['Ports']
            }
            if container.status == 'running':
                # 仅当容器处于运行中状态时获取CPU使用率信息
                try:
                    cpu_usage_percentage = container.stats(stream=False)['cpu_stats']['cpu_usage']['total_usage'] / \
                                           container.stats(stream=False)['cpu_stats']['system_cpu_usage'] * 100
                    container_data['cpu_usage_percentage'] = cpu_usage_percentage
                except KeyError:
                    # 如果不存在系统 CPU 使用率信息，则置为 None
                    container_data['cpu_usage_percentage'] = None
            containers_data.append(container_data)
        json_datas = json.dumps(containers_data,indent=4)
        print(json_datas)
        json_datas = str(json_datas)
        mqtt_client.publish(MQTT_TOPIC_to_SEND,"query!"+json_datas)



# 连接MQTT代理并订阅主题
def connect_mqtt():
    mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60)
    mqtt_client.subscribe(MQTT_TOPIC_to_RES)
    mqtt_client.on_message = on_message
    mqtt_client.loop_forever()


# 启动MQTT连接
mqtt_thread = threading.Thread(target=connect_mqtt)
mqtt_thread.start()


# Flask路由
@app.route('/')
def index():
    return render_template('index.html')


# MQTT路由
@app.route('/mqtt/messages')
def get_mqtt_messages():
    global mqtt_received_message
    return jsonify(message=mqtt_received_message)


@app.route('/mqtt/send', methods=['POST'])
def send_mqtt_message():
    message = request.form['message']
    mqtt_client.publish(MQTT_TOPIC_to_SEND, message)
    return '', 204


# RabbitMQ路由
@app.route('/rabbitmq/messages')
def get_rabbitmq_messages():
    # 创建 RabbitMQ 连接和通道
    credentials = pika.PlainCredentials('admin', 'password')
    parameters = pika.ConnectionParameters('192.168.6.236', 5672, '/', credentials)
    connection = pika.BlockingConnection(parameters)
    channel = connection.channel()

    # 声明队列
    channel.queue_declare(queue=RABBITMQ_QUEUE)

    method_frame, header_frame, body = channel.basic_get(queue=RABBITMQ_QUEUE, auto_ack=True)

    # 关闭连接
    connection.close()

    if method_frame:
        message = body.decode()
        print("RabbitMQ Received:", message)
        return jsonify(message=message)
    else:
        return jsonify(message="No messages available")


@app.route('/rabbitmq/send', methods=['POST'])
def send_rabbitmq_message():
    try:
        message = request.form['message']
        credentials = pika.PlainCredentials('admin', 'password')
        parameters = pika.ConnectionParameters('192.168.6.236', 5672, '/', credentials)
        connection = pika.BlockingConnection(parameters)
        channel = connection.channel()

        # 声明队列
        channel.queue_declare(queue=RABBITMQ_QUEUE)

        channel.basic_publish(exchange='', routing_key=RABBITMQ_QUEUE, body=message)
        connection.close()
        return '', 204
    except Exception as e:
        print("Error sending RabbitMQ message:", e)
        return jsonify(error="Error sending RabbitMQ message"), 500

def send_rabbitmq_message_2(message):
    try:
        credentials = pika.PlainCredentials('admin', 'password')
        parameters = pika.ConnectionParameters('192.168.6.236', 5672, '/', credentials)
        connection = pika.BlockingConnection(parameters)
        channel = connection.channel()

        # 声明队列
        channel.queue_declare(queue=RABBITMQ_QUEUE2)

        channel.basic_publish(exchange='', routing_key=RABBITMQ_QUEUE2, body=message)
        print("发送xxxxxxxxxxxxxxxxxx")
        connection.close()
    except Exception as e:
        print("Error sending RabbitMQ message:", e)


if __name__ == '__main__':
    app.run(debug=True,use_reloader=False, use_debugger=False, log=False)
